const express = require("express");

const { createCanvas, loadImage } = require("canvas");
const FormData = require("form-data");
const fs = require("fs");
const path = require("path");
const marked = require("marked");
const axios = require("axios");
const { config } = require("./config");

const app = express();
app.use(express.static(path.join(__dirname, "images")));
app.use(express.json());
const port = 3001;

// 假设这是获取消息的函数
async function getMessagesByIds(postData, authorization) {
  // 这里应该是从数据库或其他服务获取消息

  try {
    // console.log("token---", token);
    // 发起 GET 请求
    const response = await axios.post(
      `${config.server}/eims/BPai/wechat/getContentByShareId`,
      postData,
      {
        headers: {
          authorization,
          //   'Content-Type': 'application/json'
        },
      }
    );
    // console.log("response--", response);
    // 处理响应数据

    return response.data;
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

function processMessages(messages) {
  if (!messages || !messages.length) return [];

  return messages.map((item) => {
    let recordContent = item.recordContent
      ? JSON.parse(item.recordContent)
      : {};
    recordContent.contextMsg = recordContent.contextMsg.replace(/\\n/g, "\r\n");

    return {
      ...recordContent,
      ...item,
      status: "done",
      recommend: [],
      message: recordContent.contextMsg,
      type: recordContent.direction === "Q" ? "send" : "receive",
    };
  });
}

function canvasText(text = "查看更多", ctx) {
  // 文本样式设置
  ctx.fillStyle = "#fff";
  ctx.font = "14px sans-serif"; // 设置字体大小及字体样式

  // 计算文本宽度

  const metrics = ctx.measureText(text);
  const textWidth = metrics.width;

  // 计算文本的基线位置
  const redAreaX = 0;
  const redAreaY = 360;
  const redAreaWidth = 300;
  const redAreaHeight = 40;

  // 水平居中
  const x = redAreaX + (redAreaWidth - textWidth) / 2;

  // 垂直居中
  // measureText().actualBoundingBoxAscent 提供了文本高度的上升部分
  const textHeight =
    metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
  const y =
    redAreaY +
    (redAreaHeight + textHeight) / 2 -
    metrics.actualBoundingBoxDescent;

  // 在红色区域中绘制文本
  ctx.fillText(text, x, y);
}

app.post("/generate-image", async (req, res) => {
  try {
    let totalHei = 0;
    let isEnd = false;
    let currentY = 20;
    const { shareId, mobile } = req.body;
    const { authorization } = req.headers;
    const { result } = await getMessagesByIds(
      {
        shareId,
      },
      authorization
    );
    const query = {
      mobile,
    };
    // 转换对话列表
    let list = processMessages(result.list);

    // console.log("htmlContent--", htmlContent);
    // 设置适合小程序封面的宽高
    const width = 300;
    const height = 400;
    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext("2d");

    ctx.fillStyle = "#000000";
    ctx.fillRect(0, 0, width, height);
    ctx.fillStyle = "gray";
    ctx.globalAlpha = 0.3;
    ctx.fillRect(12, 12, width - 24, height);
    ctx.fillStyle = "#fff";
    ctx.globalAlpha = 0.6;
    ctx.fillRect(0, 360, 300, 40);

    canvasText("查看更多", ctx);

    // 设置文本样式并处理 Markdown 样式（如标题和文本）
    ctx.fillStyle = "#ffffff";
    // ctx.font = "12px sans-serif";
    ctx.textAlign = "left";
    // ctx.fillText("分享封面", 50, y);
    // y += 10;


    for (let i = 0; i < list.length; i++) {
      if (isEnd) {
        break;
      }
      try {
        let avator =
          list[i].type == "send"
            ? "images/zx-question.png"
            : "images/zx-answer.png";
        const avatarImage = await loadImage(path.join(__dirname, avator)); // 使用本地路径加载头像
        const avatarSize = 30; // 头像的大小为 30x30
        ctx.drawImage(avatarImage, 20, currentY, avatarSize, avatarSize); // 将头像绘制在指定位置
        currentY += 50;
      } catch (error) {
        console.error("Error loading avatar image:", error);
      }

      const htmlContent = marked.parse(list[i].message);
      console.log("htmlContent--", htmlContent);

      currentY = processHtml(htmlContent, ctx, currentY, canvas);
    }
    // 使用 marked 将 Markdown 转换为 HTML
    // const htmlContent = marked.parse(list[0].message);
    // processHtml(htmlContent, ctx, 70, canvas);

    // 将生成的图片保存为 PNG
    let buffer = canvas.toBuffer("image/png");

    if (!Buffer.isBuffer(buffer)) {
      buffer = Buffer.from(screenshotBuffer);
      // return;
    }

    const formData = new FormData();
    // 将 Buffer 添加到 FormData 中，作为文件上传

    // 将 Blob 添加到 FormData 对象，假设键名为 'image'
    formData.append("file", buffer, "image.jpeg");
    formData.append("fileType", "5");

    url = await uploadFile(formData);
    const imagePath = path.join(__dirname, "saveImage/share-image.png");
    fs.writeFileSync(imagePath, buffer);

    // console.log("imagePath--", imagePath);
    // saveImage(url);

    // 返回图片路径
    res.json({ code: "200", message: "操作成功", result: { url } });
  } catch (error) {
    console.error("Error fetching data:", error);
    res.status(500).json({
      success: false,
      message: "Error fetching data",
      error: error.message, // 你也可以返回更多的错误信息
    });
  }
});

const processHtml = (html, ctx, startY, canvas, currentY) => {
  let lines = html.split("\n"); // 分割行
  let y = startY;
  currentY = startY;
  console.log("lines", lines);

  lines = lines
    .map((line) => line.replace(/<[^>]+>/g, "").trim())
    .filter((item) => item);

    console.log('lines00000',lines);
    const newArray = [];

    lines.forEach(item => {
      // 使用 split(' ') 切割每一项
      const words = item.split(' ');
      
      // 将切割后的单词依次加入新数组
      newArray.push(...words);
    });
    // lines = newArray
  lines = getNewLine(newArray, ctx, 260);
  console.log("lines----", lines);
  for (let j = 0; j < lines.length; j++) {
    y = wrapText(ctx, lines[j], 20, y, canvas.width - 40, 20);
    console.log("y-----", y);
    currentY = y;
    if (currentY > 360) {
      isEnd = true;
      break;
    }
  }

  return currentY;
};


function getNewLine(originalArray, ctx, maxPixelLength) {
  // 设置字体样式（根据实际使用的字体设置）
  ctx.font = "13px sans-serif"; // 根据实际字体大小调整

  const newArray = [];


  // 遍历原始数组
  for (let item of originalArray) {
    // 计算当前文本的像素长度
    const textWidth = ctx.measureText(item).width;

    // 如果文本长度超过最大像素长度，进行切割
    if (textWidth > maxPixelLength) {
      let currentString = "";
      let remainingText = item;

      while (remainingText.length > 0) {
        const charToAdd = remainingText.charAt(0);
        const newString = currentString + charToAdd;
        const newTextWidth = ctx.measureText(newString).width;

        // 如果添加当前字符后不超过最大像素长度，继续添加
        if (newTextWidth <= maxPixelLength) {
          currentString = newString;
          remainingText = remainingText.slice(1); // 移除已添加的字符
        } else {
          // 添加到新数组并重置
          newArray.push(currentString);
          currentString = ""; // 重置当前字符串
        }
      }

      // 添加最后剩余的字符串（如果有的话）
      if (currentString.length > 0) {
        newArray.push(currentString);
      }
    } else {
      // 如果文本长度不超过最大像素长度，直接保留
      newArray.push(item);
    }
  }



  return newArray;
}

function wrapText(context, text, x, y, maxWidth, lineHeight) {
  let words = text.split(" ");
  let line = "";

  for (let n = 0; n < words.length; n++) {
    let testLine = line + words[n] + " ";
    let metrics = context.measureText(testLine);
    let testWidth = metrics.width;
    if (testWidth > maxWidth && line.length > 0) {
      context.fillText(line, x, y);
      line = words[n] + " ";
      y += lineHeight;
    } else {
      line = testLine;
    }
  }
  context.fillText(line, x, y);
  y += lineHeight; // 移动到下一行
  return y; // 返回新的y位置
}

const uploadFile = (formData) => {
  return new Promise((resolve, reject) => {
    axios
      .post(`${config.server}/tenant/manager/package/uploadFile`, formData, {
        headers: {
          // authorization,
          "Content-Type": "multipart/form-data",
          "Client-Type": "mobile",
        },
      })
      .then((res) => {
        // console.log("res--", res.data.result);
        resolve(res.data.result);
      })
      .catch((err) => {
        console.log("err----", err);
        reject(err);
      });
  });
};

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
